/**
 * 配置面板数据页签的xtag mixin 文件，
 *
 * 有特殊情况就覆写方法
 */
import STATIC_DATA from '@/common/staticData';
import { getLowCodeExpVal } from '@/components/common/low-code/low-code-util.js';
import EventBus from '@/event-bus/EventBus.js';
import dataModel from '@/models/panel-config-data.js';
import { $demoi18n } from '@/utils/lang';
import { generateExceptionRules, generateRules, genRequireRule } from '@/utils/rules';
import {
  convertFormData,
  getAggFnList,
  getFnList,
  getNormalFnList,
  getXtagAggParams,
  transformStaticDataByConfig,
} from '@/utils/util';
import { nextTick } from 'vue';
import { mapMutations, mapState } from 'vuex';

const typeAddItem = {
  type: 'add',
  'option_label': $demoi18n('word.addCustomCalculation'),
  'option_value': 'add_option_xTag',
};

export default {
  emits: ['vis-panel-data-form-clearValidate'],
  data() {
    return {
      xvueTheme: window._adoPremise.uc.theme,

      // 由mappingOptions 和 自定义计算组成
      mappingOptionsXTag: [
        {
          ...typeAddItem,
        },
      ],

      selectStyle: {
        maxWidth: '',
      },
      selectxTagStyle: {
        width: '',
      },
      mappingOptions: [],
      dataTableList: [],
      dataSourceList: [],
      apiList: [],
      isLoading: false,

      // xtag 自定义计算相关字段
      customCalculationIndex: 0,
      customCalculationCode: '',
      customCalculationType: '',
      customCalculationTitle: $demoi18n('word.addCustomCalculation'),
      customCalculationXTag: [],
      staticDataMixin: [],
      componentData: [],
      xMinerPublicDatabase: 'xMinerPublicDatabase',
    };
  },
  computed: {
    ...mapState({
      componentsData: state => state.VisualComponentsModule.componentsData,
    }),
  },
  watch: {
    mappingOptionsXTag(newVal, oldVal) {
      this.customCalculationXTag = newVal.filter(i => i.type === 'add' || i.type === 'edit');
    },
    'form.dataVal': {
      handler(val) {
        if (val) {
          this.mappingOptions = this.getMappingOptionsByExp(val);
        }
      },
      immediate: true,
    },
  },
  methods: {
    ...mapMutations(['setState', 'setPanelApiData', 'delPanelApiData']),
    generateRules,
    genRequireRule,
    generateExceptionRules,

    // 设置下拉option的title属性
    setTagTitle($event) {
      if (!$event) {
        return;
      }
      const dropdownList = document.querySelectorAll('.el-select-dropdown');
      dropdownList.forEach(item => {
        const options = item.querySelectorAll('.el-select-dropdown__item');
        options.forEach(element => {
          element.setAttribute('title', element.innerText);
        });
      });
    },

    // 设置 下拉option 的最大宽度
    setMaxWidth(val) {
      // this.selectStyle.maxWidth = `${val.srcElement.parentNode.clientWidth}px`;
    },

    // 设置 xtag下拉option 的最大宽度
    setXtagMaxWidth(val) {
      // const width = val.srcElement.parentNode.clientWidth + 30;
      // this.selectxTagStyle.width = `${width}px`;
      // this.xTagTextWidth = width - 54;
    },

    // 数据源改变--加载API列表
    dataSourceChange(value) {
      this.isLoading = true;
      this.form.dataTable = '';
      this.form.apiCode = '';
      this.clearTableDataMapping();

      const apiMethod = `getApiList${this.form.dataSourceType}`;
      dataModel[apiMethod](value)
        .then(list => {
          this.apiList = list;
        })
        .finally(() => {
          this.isLoading = false;
        });
    },

    getMappingOptionsByExp(expression) {
      let data = getLowCodeExpVal({ expression });
      if (typeof data === 'string') {
        data = [];
      }
      if (data.length === 0) {
        return [];
      }
      const options = Object.entries(data[0] || {}).map(([key]) => ({
        'option_label': key,
        'option_value': key,
      }));
      return options;
    },

    // 数据源类型改变  --加载数据源
    dataSourceTypeChange(value) {
      // 重置数据
      this.dataSourceList = [];
      this.apiList = [];
      this.mappingOptions = [];
      this.form.dataTable = '';
      this.form.dataPackage = '';
      this.form.dataSource = '';
      this.form.apiCode = '';
      this.form.dataVal = '';
      this.clearTableDataMapping();

      if (value === 'xVueApi') {
        if (window.isLocalEnv) {
          this.form.dataVal = '{{api1.data}}';
        }

        this.isLoading = true;
        setTimeout(() => {
          this.isLoading = false;
          this.clearValidate();
        }, 20);
        return;
      }

      // 如果type为静态数据,得到下拉项，结束
      if (value === 'staticData') {
        this.setMappingOptionsStaticData();
        this.clearValidate();
        return;
      }

      // xMiner/XTag/fabric/Dac 请求对应数据
      this.isLoading = true;
      const method = `getDataSourceList${value}`;
      dataModel[method]()
        .then(list => {
          this.dataSourceList = list;
        })
        .finally(() => {
          this.isLoading = false;
          this.clearValidate();
        });
    },
    clearValidate() {
      EventBus.$emit('vis-panel-data-form-clearValidate');
    },
    getApiData() {
      this.setState({
        panelApiData: [],
      });
      clearTimeout(this.getApiDataTimer);
      this.getApiDataTimer = setTimeout(() => {
        const { apiCode, tableData, dataSourceType, dataPackage, dataSource, dataVal } = this.form;
        if (dataSourceType === 'staticData') {
          const result = this.getStaticData();
          this.setPanelApiState(result);
        }

        if (dataSourceType === 'xVueApi') {
          let data = getLowCodeExpVal({ expression: this.form.dataVal });
          if (typeof data === 'string') {
            data = [];
          }

          data = data.map(n => {
            const item = {};
            tableData.forEach(n1 => {
              n1.mapping && (item[n1.field] = n[n1.mapping]);
            });
            return item;
          });

          this.setPanelApiState(data);
        }

        const dSTypes = [
          'xMiner',
          'Dac',
          this.xMinerPublicDatabase,
          'fabric',
        ];

        if (dSTypes.includes(dataSourceType)) {
          if (!apiCode) {
            return;
          }
          const method = `getChartData${dataSourceType}`;
          const params = {
            apiCode,
            propertyMapping: convertFormData(tableData),
          };
          if (dataSourceType === this.xMinerPublicDatabase) {
            params.datasourceCode = dataSource;
            params.isCommonDatasource = true;
          }
          dataModel[method](params, this.form)
            .then(result => {
              this.setPanelApiState(result);
            });
        }
        if (dataSourceType === 'xTag') {
          if (!dataPackage) {
            return;
          }
          const method = 'getChartDataxTag';
          const params = {
            conditions: [],
            propertyMapping: convertFormData(tableData),
            sqlParams: [],
          };
          getXtagAggParams(params, tableData);
          dataModel[method](params, this.form)
            .then(result => {
              this.setPanelApiState(result);
            });
        }
      }, 500);
    },
    setPanelApiState(result) {
      // 区分 左xx右xx组件
      if (this.curComp) {
        EventBus.$emit(`apiDataChanged_${this.widgetInstanceId}`, { result, comp: this.curComp });
        if (this.curComp === 'table') {
          this.setState({ panelApiTableData: result || [] });
        } else {
          this.setState({ panelApiChartData: result || [] });
        }
      } else {
        EventBus.$emit(`apiDataChanged_${this.widgetInstanceId}`, result);
        this.setPanelApiData({
          wid: this.widgetInstanceId,
          panelApiData: result || [],
        });
      }
    },
    getStaticData() {
      let data = STATIC_DATA[this.config.propertyPannelName];
      const { tableData } = this.form;
      if (this.curComp) {
        const dataMap = {
          table: `config_${process.env.xvueNameSpace_}vxe_basic_page_table`,
          gantt: `config_${process.env.xvueNameSpace_}gantt_chart`,
          shape: `config_${process.env.xvueNameSpace_}shape_chart`,
        };

        data = STATIC_DATA[dataMap[this.curComp]];
      }
      return transformStaticDataByConfig(data, tableData);
    },

    clearTableDataMapping() {
      this.form.tableData.forEach(item => {
        item.mapping = '';
      });
    },

    // xMiner API表改变   --加载表字段
    apiListChange(value) {
      this.isLoading = true;
      this.clearTableDataMapping();
      this.mappingOptions = [];
      const { id, code } = this.apiList.find(item => item.code === value);
      const method = `getMappingOptions${this.form.dataSourceType}`;
      dataModel[method](id || code)
        .then(({ list, redisKey, kafkaTopic }) => {
          this.mappingOptions = list;
          this.insertRedisKey(this.form, redisKey);
          this.insertkafkaTopic(this.form, kafkaTopic);
        })
        .finally(() => {
          this.isLoading = false;
        });
    },

    // 加载配置数据
    loadData(config) {
      let _config = config;
      if (!_config.dataSourceType && this.curComp) {
        _config = _config[this.curComp];
      }
      const { dataSourceType } = _config;
      if (dataSourceType) {
        this[`loadData${dataSourceType}`](_config);
      }
    },
    loadDatastaticData(config) {
      const { dataSourceType, tableData } = config;
      this.form.dataSourceType = dataSourceType;
      this.initStaticData();
      this.setMappingOptionsStaticData();

      // 深拷贝修改指向，否则不会触发panel-data-common里的watch
      this.form.tableData = [...tableData];
    },
    loadDataxVueApi(config) {
      const { dataSourceType, tableData } = config;
      this.form.dataSourceType = dataSourceType;

      // 深拷贝修改指向，否则不会触发panel-data-common里的watch
      this.form.tableData = [...tableData];
    },
    loadDataxMiner(config) {
      const { dataSourceType, dataSource, dataTable, apiCode, tableData } = config;
      this.isLoading = true;
      this.form.dataSourceType = dataSourceType;

      // 获取数据源
      dataModel[`getDataSourceList${dataSourceType}`]()
        .then(dataSourceList => {
          this.form.dataSource = dataSource;
          this.dataSourceList = dataSourceList;
          if (dataSource) {
            // 获取api 列表
            dataModel[`getApiList${dataSourceType}`](dataSource)
              .then(apiList => {
                this.apiList = apiList;
                this.form.apiCode = apiCode;

                // 获取API的属性字段列表
                if (apiCode) {
                  const { id, code } = apiList.find(item => item.code === apiCode) || {};
                  const _idCode = dataSourceType === 'fabric' ? code : id;
                  if (_idCode) {
                    dataModel[`getMappingOptions${dataSourceType}`](_idCode)
                      .then(({ list, redisKey, kafkaTopic }) => {
                        this.mappingOptions = list;
                        this.form.tableData = [...tableData];
                        this.insertRedisKey(this.form, redisKey);
                        this.insertkafkaTopic(this.form, kafkaTopic);
                      })
                      .finally(() => {
                        this.isLoading = false;
                      });
                  } else {
                    this.isLoading = false;
                  }
                } else {
                  this.isLoading = false;
                }
              });
          } else {
            this.isLoading = false;
          }
        });
    },

    loadDatafabric(config) {
      return this.loadDataxMiner(config);
    },

    loadDataDac(config) {
      return this.loadDataxMiner(config);
    },

    loadDataxMinerRedisRealTime(config) {
      return this.loadDataxMiner(config);
    },
    loadDatakafka(config) {
      return this.loadDataxMiner(config);
    },

    insertRedisKey(form, redisKey) {
      if (form.dataSourceType === 'xMinerRedisRealTime') {
        form.redisKey = redisKey;
      }
    },
    insertkafkaTopic(form, kafkaTopic) {
      if (form.dataSourceType === 'kafka') {
        form.kafkaTopic = kafkaTopic;
      }
    },
    loadDataxMinerPublicDatabase(config) {
      const { dataSourceType, dataSource, dataTable, apiCode, tableData } = config;
      this.isLoading = true;
      this.form.dataSourceType = dataSourceType;

      // 获取数据源
      dataModel[`getDataSourceList${dataSourceType}`]()
        .then(dataSourceList => {
          this.dataSourceList = dataSourceList;
          this.form.dataSource = dataSource;
          if (dataSource) {
            // 获取api 列表
            dataModel[`getApiList${dataSourceType}`](dataSource)
              .then(apiList => {
                this.apiList = apiList;
                this.form.apiCode = apiCode;

                // 获取API的属性字段列表
                if (apiCode) {
                  const api = apiList.find(item => item.code === apiCode);
                  if (api && api.id) {
                    dataModel[`getMappingOptions${dataSourceType}`](api.id)
                      .then(({ list }) => {
                        this.mappingOptions = list;
                        this.form.tableData = [...tableData];
                      })
                      .finally(() => {
                        this.isLoading = false;
                      });
                  } else {
                    this.isLoading = false;
                  }
                } else {
                  this.isLoading = false;
                }
              });
          } else {
            this.isLoading = false;
          }
        });
    },

    _getMappingOptionsCallback(config, mappingOptions) {
      const { tableData, customCalculationXTag = [] } = config;
      this.mappingOptions = mappingOptions;
      this.form.tableData = [...tableData];

      // ---- 补全函数备选项
      let customOpts = [...customCalculationXTag];
      const lackOpts = [];
      const fnList = getFnList();
      tableData.forEach(n => {
        const hasItem = customOpts.some(n1 => n1.option_value === n.mapping);
        const isFn = fnList.some(name => n.mapping.includes(`${name}(`));
        if (!hasItem && isFn) {
          lackOpts.push({
            type: 'edit',
            'option_label': n.mapping,
            'option_value': n.mapping,
          });
        }
      });
      customOpts = [...customOpts, ...lackOpts];

      // ---- 补充“添加计算公式”
      const options = [...customOpts, ...mappingOptions];
      const hasTypeAdd = options.find(n => n.type === 'add');
      if (!hasTypeAdd) {
        options.unshift({ ...typeAddItem });
      }
      this.mappingOptionsXTag = options;
    },

    loadDataxTag(config) {
      const { dataSourceType, dataPackage, dataTable, tableData, customCalculationXTag = [] } = config;
      this.isLoading = true;
      this.form.dataSourceType = dataSourceType;

      // 获取数据源
      dataModel[`getDataSourceList${dataSourceType}`]()
        .then(dataSourceList => {
          this.dataSourceList = dataSourceList;
          this.form.dataPackage = dataPackage;
          if (dataPackage) {
            const apiMethod = `getApiList${dataSourceType}`;
            dataModel[apiMethod](dataPackage)
              .then(list => {
                this.apiList = list;
                this.form.dataTable = dataTable;
                if (dataTable) {
                  dataModel[`getMappingOptions${dataSourceType}`](dataTable, dataPackage)
                    .then(res => {
                      this._getMappingOptionsCallback(config, res);
                      this.insertRedisKey(this.form, res.redisKey);
                      this.insertkafkaTopic(this.form, res.kafkaTopic);
                    })
                    .finally(() => {
                      this.isLoading = false;
                    });
                }
              })
              .finally(() => {
                this.isLoading = false;
              });
          } else {
            this.isLoading = false;
          }
        })
        .finally(() => {
          this.isLoading = false;
        });
    },
    updateMappingOptionsXTag(obj) {
      if (!this.curRow) {
        return;
      }
      this.curRow.mapping = obj.code;
      if (obj.type === 'add') {
        this.curRow.type = 'edit';
        if (this.mappingOptionsXTag.length === 1) {
          this.mappingOptionsXTag.push({
            type: 'edit',
            'option_label': obj.code,
            'option_value': obj.code,
          });
        } else {
          this.mappingOptionsXTag.splice(1, 0, {
            type: 'edit',
            'option_label': obj.code,
            'option_value': obj.code,
          });
        }
      } else if (obj.type === 'edit') {
        this.mappingOptionsXTag.splice(obj.index, 1, {
          type: 'edit',
          'option_label': obj.code,
          'option_value': obj.code,
        });
      } else {}

      // 改变内存地址，触发watch
      this.mappingOptionsXTag = [...this.mappingOptionsXTag];
    },

    // 给表格数据 增加xtag自定义计算类型
    optionxTagChange(row) {
      if (row.mapping) {
        // 不取this.customCalculationXTag，因为添加新计算公式时该数组还不包含该项
        const customCalculationXTag = this.mappingOptionsXTag.filter(i => i.type === 'add' || i.type === 'edit');
        const option = customCalculationXTag.find(o => o.option_value === row.mapping);
        if (option) {
          row.type = option.type;
        }

        // 是否包含聚合函数字段
        const aggFnList = getAggFnList();
        const hasAggFn = aggFnList.some(name => row.mapping.includes(`${name}(`));

        // 是否包含普通函数
        const normalFnList = getNormalFnList();
        const hasNormalFn = normalFnList.some(name => row.mapping.includes(`${name}(`));

        if (hasAggFn || hasNormalFn) {
          row.type = 'edit';
        }
      } else {
        row.type = '';
      }
      if (this.autoFill) {
        this.autoFill(row);
      }
    },
    optionxTagClick(item, row, from) {
      let self = this;
      if (from && from === 'fromChild') {
        self = this.$parent;
      }
      self.curRow = row;
      if (!self.form.dataTable) {
        self.$message({
          message: $demoi18n('message.plsSelectDataTable'),
          type: 'warning',
        });
        return;
      }
      const index = self.mappingOptionsXTag.findIndex(option => option.option_label === item.option_label);

      self.customCalculationIndex = index;
      self.customCalculationType = item.type;
      if (item.type === 'add') {
        self.customCalculationTitle = $demoi18n('word.addCustomCalculation');
        self.customCalculationCode = '';
        self.openCustomCalculation(row);
      } else if (item.type === 'edit') {
        self.customCalculationTitle = $demoi18n('word.editCustomCalculation');
        self.customCalculationCode = item.option_label;
        self.openCustomCalculation(row);
      } else {}
    },
    optionxTagDelete(index) {
      const _this = this.commonComp || this;
      _this.mappingOptionsXTag.splice(index, 1);
    },
    showPreview() {
      if (!this.form.dataTable) {
        this.$message({
          message: $demoi18n('message.plsSelectDataTable'),
          type: 'warning',
        });
        return;
      }
      if (this.$refs.myFlatWideTable) {
        this.$refs.myFlatWideTable.openDialog();
      }
    },
    openCustomCalculation(row) {
      const _this = this.commonComp || this;
      if (_this.$refs.myCustomCalculation) {
        nextTick(() => {
          _this.$refs.myCustomCalculation.openDialog(row);
        });
      }
    },

    // 数据表改变   --加载表字段  --xtag
    dataTableChange(value) {
      this.isLoading = true;
      this.clearTableDataMapping();
      this.mappingOptions = [];
      this.mappingOptionsXTag = [
        {
          ...typeAddItem,
        },
      ];
      if (!value) {
        this.isLoading = false;
        return;
      }
      const tableName = this.apiList.find(item => item.option_value === value).option_label;
      const method = `getMappingOptions${this.form.dataSourceType}`;
      dataModel[method](tableName, this.form.dataPackage)
        .then(list => {
          this.mappingOptions = list;
          this.mappingOptionsXTag = [...this.mappingOptionsXTag, ...this.mappingOptions];
        })
        .finally(() => {
          this.isLoading = false;
        });
    },

    // xTag  数据包改变
    dataPackageChange(value) {
      this.isLoading = true;
      this.apiList = [];
      this.form.dataTable = '';
      this.clearTableDataMapping();
      const apiMethod = `getApiList${this.form.dataSourceType}`;
      dataModel[apiMethod](value)
        .then(_list => {
          this.apiList = _list;
        })
        .finally(() => {
          this.isLoading = false;
        });
    },

    // 初始化静态数据
    initStaticData() {
      this.staticDataMixin = STATIC_DATA[this.config?.propertyPannelName];
      if (this.curComp) {
        const dataMap = {
          table: `config_${process.env.xvueNameSpace_}vxe_basic_page_table`,
          gantt: `config_${process.env.xvueNameSpace_}gantt_chart`,
          shape: `config_${process.env.xvueNameSpace_}shape_chart`,
        };
        this.staticDataMixin = STATIC_DATA[dataMap[this.curComp]];
      }
    },

    // 更新配置页面中的样例数据
    updateExampleData(data) {
      const exampleData = [...data];
      const exampleDataLength = 3; // 展示示例数据的数量
      if (exampleData.length > exampleDataLength) {
        exampleData.length = exampleDataLength;
      }
      this.result = JSON.stringify(exampleData, null, 2);
    },

    // 通过静态数据设置mappingOptions
    setMappingOptionsStaticData() {
      const mappingOptions = dataModel.getMappingOptionsstaticData(this.staticDataMixin);
      this.mappingOptions = mappingOptions;
    },
    xTagTableDataChange(row) {
      this.optionxTagChange(row);
      this.getApiData();
    },
    xMinerTableDataChange(row) {
      this.getApiData();
    },
  },
  created() {
    this.initStaticData();
    EventBus.$on(`save_customCalculation_${this.widgetInstanceId}`, ({ obj, row }) => {
      this.updateMappingOptionsXTag(obj);
      this.xTagTableDataChange(row);
    });

    // 获取当前组件的数据
    EventBus.$on(`vis_getChartData${this.widgetInstanceId}`, ({ data }) => {
      if (data && Array.isArray(data)) {
        this.updateExampleData(data);
      }
    });
  },
  mounted() {
    // 初始化配置页面中的样例数据
    const data = this.componentsData && this.componentsData[this.widgetInstanceId];
    this.componentData = data;
    if (data && Array.isArray(data)) {
      this.updateExampleData(data);
    }
  },
  beforeUnmount() {
    EventBus.$off(`save_customCalculation_${this.widgetInstanceId}`);
    EventBus.$off(`vis_getChartData${this.widgetInstanceId}`);
  },
};
